using System;
using System.Runtime.InteropServices;

namespace Framework.Interop
{
    [ComVisible(false)]
    [CLSCompliant(false)]
    internal static class Shell32
    {
        /// <summary>
        /// Retrieves the Shell's IMalloc interface.
        /// </summary>
        /// <returns>The Shell's IMalloc interface.</returns>
        internal static Malloc GetMalloc()
        {
            IntPtr pMalloc;
            Marshal.ThrowExceptionForHR(SHGetMalloc(out pMalloc));
            return new Malloc(pMalloc);
        }

        /// <summary>
        /// Performs an operation on a specified file.
        /// <seealso>
        /// Native <see cref="http://msdn.microsoft.com/en-us/library/bb762154.aspx">method</see>.
        /// </seealso>
        /// </summary>
        /// <param name="lpExecInfo">A pointer to a <see cref="ShellExecuteInfo">ShellExecuteInfo</see> structure that contains
        /// and receives information about the application being executed.</param>
        /// <returns>Returns TRUE if successful; otherwise, FALSE. Call <see cref="Marshal.GetLastWin32Error">GetLastError</see>
        /// for extended error information.</returns>
        [DllImport("shell32.dll", SetLastError = true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        internal static extern bool ShellExecuteEx(ref ShellExecuteInfo lpExecInfo);

        /// <summary>
        /// Retrieves a pointer to the Shell's IMalloc interface.
        /// <seealso>
        /// Native <see cref="http://msdn.microsoft.com/en-us/library/bb762190.aspx">method</see>.
        /// </seealso>
        /// </summary>
        /// <param name="ppMalloc">The address of a pointer that receives the Shell's IMalloc interface pointer.</param>
        /// <returns>If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
        [DllImport("shell32.dll")]
        internal static extern int SHGetMalloc(out IntPtr ppMalloc);

        /// <summary>
        /// Creates a new instance of the default Shell folder view object.
        /// <seealso>
        /// Native <see cref="http://msdn.microsoft.com/en-us/library/bb762141.aspx">method</see>.
        /// </seealso>
        /// </summary>
        /// <param name="pcsfv">Pointer to a <see cref="ShellFolderViewCreate">Sfv_Create</see> structure that describes the particulars used in
        /// creating this instance of the Shell folder view object.</param>
        /// <param name="ppsv">When this function returns successfully, contains an interface pointer to the new
        /// <see cref="http://msdn.microsoft.com/en-us/library/bb774834.aspx">IShellView</see> object. On failure, this value is
        /// NULL.</param>
        /// <returns>If the method succeeds, it returns S_OK. Otherwise, it returns an HRESULT error code.</returns>
        [DllImport("shell32.dll")]
        internal static extern int SHCreateShellFolderView(
            [MarshalAs(UnmanagedType.Struct)] ref ShellFolderViewCreate pcsfv, out IntPtr ppsv);

        /// <summary>
        /// Notifies the system of an event that an application has performed. An application should use this function if it
        /// performs an action that may affect the Shell.
        /// </summary>
        /// <param name="wEventId">Describes the event that has occurred. Typically, only one event is specified at a time. If more
        /// than one event is specified, the values contained in the <see cref="dwItem1">dwItem1</see> and
        /// <see cref="dwItem2">dwItem2</see> parameters must be the same, respectively, for all specified events.</param>
        /// <param name="uFlags">Flags that, when combined bitwise with <see cref="SHChangeNotifyFlags.Type">Type flag</see>,
        /// indicate the meaning of the <see cref="dwItem1">dwItem1</see> and <see cref="dwItem2">dwItem2</see> parameters.</param>
        /// <param name="dwItem1">Optional. First event-dependent value.</param>
        /// <param name="dwItem2">Optional. Second event-dependent value.</param>
        [DllImport("shell32.dll")]
        internal static extern void SHChangeNotify(SHChangeNotifyEvents wEventId, SHChangeNotifyFlags uFlags,
                                                   IntPtr dwItem1, IntPtr dwItem2);
    } ;
}
